﻿// <copyright file="AreaValidator.cs" company="City of Portland, BES-ASM">
// </copyright>
// <summary>AreaValidator class</summary>

namespace BESASM.EMGAATS.BusinessClasses
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using FluentValidation;

  /// <summary>
  /// A class for validating Area instances
  /// </summary>
  public class AreaValidator : AbstractValidator<IArea>
  {
    /// <summary>
    /// Initializes a new instance of the <see cref="AreaValidator"/> class.
    /// </summary>
    /// <param name="ruleSet">The set of rules to apply.</param>
    public AreaValidator(RuleSet ruleSet)
    {
      // Universal rules
      this.DirectorsListNotNull();

      // RuleSet rules
      switch (ruleSet)
      {
        case BusinessClasses.RuleSet.MasterDataCommit:
          this.AreaGreaterThanZero(ErrorLevel.Error);
          this.SanitaryFlowGreaterThanOrEqualToZero(ErrorLevel.Error);
          this.SlopeGreaterThanZero(ErrorLevel.Error);
          this.FlowLengthGreaterThanZero(ErrorLevel.Error);
          break;
        case BusinessClasses.RuleSet.ModelDataCommit:
          this.AreaGreaterThanZero(ErrorLevel.Error);
          this.SanitaryFlowGreaterThanOrEqualToZero(ErrorLevel.Error);
          this.SlopeGreaterThanZero(ErrorLevel.Error);
          this.FlowLengthGreaterThanZero(ErrorLevel.Error);
          break;
        case BusinessClasses.RuleSet.ModelDeployment:
          this.AreaGreaterThanZero(ErrorLevel.Error);
          this.SanitaryFlowGreaterThanOrEqualToZero(ErrorLevel.Error);
          this.SlopeGreaterThanZero(ErrorLevel.Error);
          this.FlowLengthGreaterThanZero(ErrorLevel.Error);
          break;
        case BusinessClasses.RuleSet.NetworkTracing:
          // none
          break;
        case BusinessClasses.RuleSet.PropertyDialog:
          this.AreaGreaterThanZero(ErrorLevel.Warning);
          this.SanitaryFlowGreaterThanOrEqualToZero(ErrorLevel.Warning);
          this.SlopeGreaterThanZero(ErrorLevel.Warning);
          this.FlowLengthGreaterThanZero(ErrorLevel.Warning);
          break;
      }
    }

    private void AreaGreaterThanZero(ErrorLevel level)
    {
      RuleFor(area => area.AreaSqFt)
        .GreaterThan(0)
        .WithState(area => new ValidationState(area, level))
        .WithMessage("Area (Id: {0}) does not have an area greater than zero.", area => area.Id);
    }

    private void FlowLengthGreaterThanZero(ErrorLevel level)
    {
      RuleFor(area => area.FlowLengthFt)
        .GreaterThan(0)
        .WithState(area => new ValidationState(area, level))
        .WithMessage("Area (Id: {0}) does not have a flow length greater than zero.", area => area.Id);
    }

    private void SlopeGreaterThanZero(ErrorLevel level)
    {
      RuleFor(area => area.SlopeFtPerFt)
        .GreaterThanOrEqualTo(0)
        .WithState(area => new ValidationState(area, level))
        .WithMessage("Area (Id: {0}) does not have a slope greater than or equal to zero.", area => area.Id);
    }

    private void SanitaryFlowGreaterThanOrEqualToZero(ErrorLevel level)
    {
      RuleFor(area => area.SanitaryFlowCfs)
        .GreaterThanOrEqualTo(0)
        .WithState(area => new ValidationState(area, level))
        .WithMessage("Area (Id: {0}) does not have a sanitary flow zero or greater.", area => area.Id);
    }

    private void DirectorsListNotNull()
    {
      RuleFor(area => area.Directors)
        .NotNull()
        .WithState(area => new ValidationState(area, ErrorLevel.Error))
        .WithMessage("Area (Id: {0}) has a null directors list.", area => area.Id);
    }
  }
}
